/*
                    AI Implementation
*/
#include "AI.h"

void AI::Initialise(Map& currentMap)
{
    Pathfinder.Initialise(currentMap);
}

void AI::Quit()
{
    Pathfinder.Quit();
}

void AI::HandleAI(vector<Player*>& Players, vector<Food*>& FoodObjects)
{
    for (int i = 0; i < Players.size(); i++)
    {
        if (Players.at(i)->isCPU() == true)
        {
            if (Players.at(i)->getTargetFood() == -1)
            {
                FindNewTargetFood(i, Players, FoodObjects);
            }

      /*    leaving this commented out as it may be used when we start adding personalities etc -ben

            if (Players.at(i)->getNeedsNewPath() == true)
            {
                Players.at(i)->setNeedsNewPath(false);

                Players.at(i)->setPath(Pathfinder.GeneratePath(
                                        Players.at(i),
                                        FoodObjects.at(Players.at(i)->getTargetFood())->getPosition(),
                                        Players.at(i)->getPosition(),
                                        Players.at(i)->getSnake().getDirection(),
                                        Players
                                        ));
            }*/


            Players.at(i)->setPath(Pathfinder.GeneratePath(
                        Players.at(i),
                        FoodObjects.at(Players.at(i)->getTargetFood())->getPosition(),
                        Players.at(i)->getPosition(),
                        Players.at(i)->getSnake().getDirection(),
                        Players
                        ));

        }
    }
}

/*
    This function will find the closest food to the current AI player ignoring collisions and obstacles in the way.
*/
void AI::FindNewTargetFood(int id, vector<Player*>& Players, vector<Food*>& FoodObjects)
{
    if (FoodObjects.size() <= 0) { return; }

    int iCurrentFood = 0;
    double dDistance, dEnemyDist, dClosestEnemy, dScore, dCurrentScore;
    bool bEnemySet = false;
    bool bScoreSet = false;


    for (int i = 0; i < FoodObjects.size(); i++)
    {
        dDistance = FoodObjects.at(i)->getPosition().DistanceFromPoint(Players.at(id)->getPosition());

        for (int j = 0; j < Players.size(); j++)
        {
            if (j != id)
            {
                dEnemyDist = FoodObjects.at(i)->getPosition().DistanceFromPoint(Players.at(j)->getPosition());

                if ((dEnemyDist < dClosestEnemy) || !bEnemySet)
                {
                    dClosestEnemy = dEnemyDist;

                    if (Players.at(id)->getPersonality())
                    {
                        dScore  = dDistance + (Players.at(id)->getPersonality() - dEnemyDist);
                        if(dEnemyDist < (Players.at(id)->getPersonality()))
                            dScore += 50 *(Players.at(id)->getPersonality() - dEnemyDist);
                    }
                    else
                        dScore = dDistance;

                    bEnemySet = true;
                }
            }
        }

        if ((dScore < dCurrentScore) || !bScoreSet)
        {
            iCurrentFood = i;
            dCurrentScore = dScore;
            bScoreSet = true;
        }

        bEnemySet = false;
    }

    Players.at(id)->setTargetFood(iCurrentFood);
    Players.at(id)->setNeedsNewPath(true);
}
